"""
作者：Leagolas
日期：2024年06月12日
"""
import pandas as pd
import numpy as np
import math




def Parkison_volatility(pd_data, window):
    process_data = pd_data.copy()
    process_data["对数最高价"] = np.log(process_data['最高价'])
    process_data["对数最低价"] = np.log(process_data['最低价'])
    process_data["对数高低价差"] = process_data["对数最高价"] - process_data["对数最低价"]
    process_data["对数高低差滚动平方和"] = process_data["对数高低价差"].rolling(window=window).apply(lambda x: (x**2).sum())

    process_data["Parkinson波动率估计量"] = np.sqrt(process_data["对数高低差滚动平方和"] / (4 * window * math.log(2)))

    return process_data[["交易日", "Parkinson波动率估计量"]]


def Garman_Klass_volatility(pd_data, window):
    # 书上的表达式有可能算出负数

    process_data = pd_data.copy()
    process_data["对数最高价"] = np.log(process_data['最高价'])
    process_data["对数最低价"] = np.log(process_data['最低价'])
    process_data["对数高低价差"] = process_data["对数最高价"] - process_data["对数最低价"]
    process_data["对数高低差滚动平方和"] = process_data["对数高低价差"].rolling(window=window).apply(lambda x: (x**2).sum())

    process_data["对数收盘价"] = np.log(process_data['收盘价'])
    process_data["对数前收盘价"] = np.log(process_data['前收盘价'])
    process_data["对数收盘价差"] = process_data['对数收盘价'] - process_data["对数前收盘价"]
    process_data["对数收盘价差滚动平方和"] = process_data["对数收盘价差"].rolling(window=window).apply(lambda x: (x**2).sum())


    process_data["Garman_Klass波动率估计量"] = np.sqrt(process_data["对数高低差滚动平方和"] / (2 * window) - (2 * math.log(2) - 1) * process_data["对数收盘价差滚动平方和"] / window)

    return process_data[["交易日", "Garman_Klass波动率估计量"]]


def Open_Open_volatility(pd_data, window):
    process_data = pd_data.copy()
    process_data["对数开盘价"] = np.log(process_data['开盘价'])
    process_data["对数前开盘价"] = np.log(process_data['前开盘价'])
    process_data["对数开盘价差"] = process_data['对数开盘价'] - process_data["对数前开盘价"]

    process_data["对数开盘价差滚动平均"] = process_data['对数开盘价差'].rolling(window=window).sum() / window
    process_data["作差"] =  process_data["对数开盘价差"] - process_data["对数开盘价差滚动平均"]

    process_data["Open_Open波动率估计量"]  = np.sqrt(process_data["对数开盘价差"].rolling(window=window).apply(lambda x: (x**2).sum()) / (window - 1))

    return process_data[["交易日", "Open_Open波动率估计量"]]


def Close_Close_volatility(pd_data, window):
    process_data = pd_data.copy()
    process_data["对数收盘价"] = np.log(process_data['收盘价'])
    process_data["对数前收盘价"] = np.log(process_data['前收盘价'])
    process_data["对数收盘价差"] = process_data['对数收盘价'] - process_data["对数前收盘价"]

    process_data["对数收盘价差滚动平均"] = process_data['对数收盘价差'].rolling(window=window).sum() / window
    process_data["作差"] = process_data["对数收盘价差"] - process_data["对数收盘价差滚动平均"]

    process_data["Close_Close波动率估计量"] = np.sqrt(process_data["对数收盘价差"].rolling(window=window).apply(lambda x: (x ** 2).sum()) / (window - 1))

    return process_data[["交易日", "Close_Close波动率估计量"]]



def Rogers_Satchell_Yoon_volatility(pd_data, window):

    process_data = pd_data.copy()
    process_data["对数最高价"] = np.log(process_data['最高价'])
    process_data["对数最低价"] = np.log(process_data['最低价'])
    process_data["对数开盘价"] = np.log(process_data['开盘价'])
    process_data["对数收盘价"] = np.log(process_data['收盘价'])

    process_data["对数差1"] = process_data["对数最高价"] - process_data["对数收盘价"]
    process_data["对数差2"] = process_data["对数最高价"] - process_data["对数开盘价"]
    process_data["对数差3"] = process_data["对数最低价"] - process_data["对数收盘价"]
    process_data["对数差4"] = process_data["对数最低价"] - process_data["对数开盘价"]

    process_data["对数差1乘对数差2"] = process_data["对数差1"] * process_data["对数差2"]
    process_data["对数差3乘对数差4"] = process_data["对数差3"] * process_data["对数差4"]

    process_data["成分1"] = process_data["对数差1乘对数差2"].rolling(window=window).sum() / window
    process_data["成分2"] = process_data["对数差3乘对数差4"]

    process_data["Rogers_Satchell_Yoon波动率估计量"] = np.sqrt(process_data["成分1"] + process_data["成分2"])

    return process_data[["交易日", "Rogers_Satchell_Yoon波动率估计量"]]



def Yang_Zhang_volatility(pd_data, window):
    process_data = pd_data.copy()

    process_data['Open_Open波动率估计量'] = Open_Open_volatility(pd_data, window)["Open_Open波动率估计量"] ** 2
    process_data['Close_Close波动率估计量'] = Close_Close_volatility(pd_data, window)["Close_Close波动率估计量"] ** 2
    process_data["Rogers_Satchell_Yoon波动率估计量"] = Rogers_Satchell_Yoon_volatility(pd_data, window)["Rogers_Satchell_Yoon波动率估计量"] ** 2
    weight = 0.34 / (1.34 + (window + 1) / (window - 1))

    process_data["Yang_Zhang波动率估计量"] = np.sqrt(process_data['Open_Open波动率估计量'] + weight * process_data['Close_Close波动率估计量'] + (1 - weight) * process_data["Rogers_Satchell_Yoon波动率估计量"])

    return process_data[["交易日", "Yang_Zhang波动率估计量"]]








